{***************************************************************************}
{                                                                           }
{           Spring Framework for Delphi                                     }
{                                                                           }
{           Copyright (C) 2009-2011 DevJET                                  }
{                                                                           }
{           http://www.spring4d.org                                         }
{                                                                           }
{***************************************************************************}
{                                                                           }
{  Licensed under the Apache License, Version 2.0 (the "License");          }
{  you may not use this file except in compliance with the License.         }
{  You may obtain a copy of the License at                                  }
{                                                                           }
{      http://www.apache.org/licenses/LICENSE-2.0                           }
{                                                                           }
{  Unless required by applicable law or agreed to in writing, software      }
{  distributed under the License is distributed on an "AS IS" BASIS,        }
{  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. }
{  See the License for the specific language governing permissions and      }
{  limitations under the License.                                           }
{                                                                           }
{***************************************************************************}

unit Spring.Serialization.Formatter.XMLDocument;

{$I Spring.inc}

interface
uses
{$IFDEF DELPHIXE2}
  Xml.xmldom,
  Xml.XMLIntf,
  Xml.Win.msxmldom,
  Xml.XMLDoc,
{$ELSE}
  xmldom,
  XMLIntf,
  msxmldom,
  XMLDoc,
{$ENDIF}
  Classes,
  SysUtils,
  Rtti,
  Generics.Collections,
  Variants,
  Spring,
  Spring.Collections,
  Spring.Serialization.Formatter;

type
  TXmlFormatter = class(TFormatterBase, IFormatter, IInterface)
  protected
    procedure ContentToTree(const stream: TStream; const document: IContentDocument); override;
    procedure TreeToContent(const stream: TStream; const document: IContentDocument); override;
  end;

implementation

uses
  Spring.Serialization,
  Spring.Serialization.ResourceStrings;

{ TXmlBackend_TXmlDocument }

procedure TXmlFormatter.TreeToContent(const stream: TStream;
  const document: IContentDocument);

  procedure NodeToXmlNode(const node: IContentNode; const xmlNode: IXmlNode);
  var
    child: IContentNode;
  begin
    if node.Children.IsEmpty then
      if node.Value <> '' then
        xmlNode.NodeValue := node.Value
      else
    else
      for child in node.Children do
        NodeToXmlNode(child, xmlNode.AddChild(child.Name));
  end;

var
  fXmlDocument: IXmlDocument;
begin
  fXmlDocument := NewXmlDocument;
  fXmlDocument.Options := fXmlDocument.Options + [doNodeAutoIndent];
  fXmlDocument.DocumentElement := fXmlDocument.CreateElement(document.Root.Name, '');
  NodeToXmlNode(document.Root, fXmlDocument.DocumentElement);

  fXMLDocument.SaveToStream(stream);
end;

procedure TXmlFormatter.ContentToTree(const stream: TStream;
  const document: IContentDocument);

  procedure XmlNodeToNode(const xmlNode: IXmlNode; const node: IContentNode);
  var
    i: integer;
  begin
    node.Name := xmlNode.NodeName;

    if xmlNode.ChildNodes.Count = 0 then
      if xmlNode.NodeValue <> null then
        node.Value := xmlNode.NodeValue
      else
    else
      for i := 0 to xmlNode.ChildNodes.Count - 1 do
        XmlNodeToNode(xmlNode.ChildNodes.Nodes[I], node.AddChild);
  end;

var
  fXmlDocument: IXmlDocument;
begin
  document.Root.Clear;
  try
    fXmlDocument := NewXMLDocument;
    fXmlDocument.LoadFromStream(stream);
  except
    raise ESerializationSourceCodeException.CreateRes(@SCodeNotFound);
  end;
  XmlNodeToNode(fXmlDocument.DocumentElement, document.Root);
end;

end.
